home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Online / opennap / hashlist.c < prev    next >
C/C++ Source or Header  |  2001-06-08  |  4KB  |  192 lines

  1. /* Copyright (C) 2000-1 drscholl@users.sourceforge.net
  2.    This is free software distributed under the terms of the
  3.    GNU Public License.  See the file COPYING for details.
  4.  
  5.    $Id: hashlist.c,v 1.8 2001/02/15 08:39:45 drscholl Exp $ */
  6.  
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include "list.h"
  10. #include "hash.h"
  11. #include "hashlist.h"
  12. #include "opennap.h"
  13. #include "debug.h"
  14.  
  15. hashlist_t *
  16. hashlist_add (HASH * h, void *key, void *data)
  17. {
  18.     hashlist_t *hl;
  19.  
  20.     ASSERT (key != 0);
  21.     hl = hash_lookup (h, key);
  22.     if (!hl)
  23.     {
  24.     hl = CALLOC (1, sizeof (hashlist_t));
  25.     if (!hl)
  26.     {
  27.         OUTOFMEMORY ("hashlist_add");
  28.         return 0;
  29.     }
  30. #if DEBUG
  31.     hl->magic = MAGIC_HASHLIST;
  32. #endif
  33.     /* TODO: this should probably be user-configurable */
  34.     if (h->hash_key == hash_string)
  35.     {
  36.         hl->key = STRDUP (key);
  37.         if (!hl->key)
  38.         {
  39.         OUTOFMEMORY ("hashlist_add");
  40.         memset (hl, 0xff, sizeof (hashlist_t));
  41.         FREE (hl);
  42.         return 0;
  43.         }
  44.     }
  45.     else
  46.         hl->key = key;
  47.     if (hash_add (h, hl->key, hl))
  48.     {
  49.         FREE (hl->key);
  50.         memset (hl, 0xff, sizeof (hashlist_t));
  51.         FREE (hl);
  52.         return 0;
  53.     }
  54.     }
  55.     ASSERT (hashlist_validate (hl));
  56.     if (data)
  57.     {
  58.     LIST   *list;
  59.  
  60.     if (list_find (hl->list, data))
  61.     {
  62.         /* already present */
  63.         return 0;
  64.     }
  65.  
  66.     list = MALLOC (sizeof (LIST));
  67.     if (!list)
  68.     {
  69.         OUTOFMEMORY ("hashlist_add");
  70.         if (hl->count == 0)
  71.         {
  72.         ASSERT (hl->list == 0);
  73.         hash_remove (h, hl->key);
  74.         }
  75.         if (h->hash_key == hash_string)
  76.         FREE (hl->key);
  77.         memset (hl, 0xff, sizeof (hashlist_t));
  78.         FREE (hl);
  79.         return 0;
  80.     }
  81.     list->data = data;
  82.     hl->list = list_push (hl->list, list);
  83.     }
  84.     hl->count++;
  85.     return hl;
  86. }
  87.  
  88. int
  89. hashlist_remove (HASH * h, void *key, void *data)
  90. {
  91.     hashlist_t *hl;
  92.  
  93.     ASSERT (key != 0);
  94.     if ((hl = hash_lookup (h, key)) == 0)
  95.     return -1;
  96.  
  97.     ASSERT (hashlist_validate (hl));
  98.     ASSERT (hl->count > 0);
  99.     if (data)
  100.     {
  101.     LIST  **cur;
  102.     LIST   *tmp = 0;
  103.  
  104.     ASSERT (hl->list != 0);
  105.     /* don't use list_delete() here since we need to ensure that
  106.      * the member was actually part of the list in order to
  107.      * succeed.
  108.      */
  109.     for (cur = &hl->list; *cur;)
  110.     {
  111.         if ((*cur)->data == data)
  112.         {
  113.         tmp = *cur;
  114.         *cur = (*cur)->next;
  115.         FREE (tmp);
  116.         break;
  117.         }
  118.         cur = &(*cur)->next;
  119.     }
  120.     if (!tmp)
  121.     {
  122.         /* element was not found on the list */
  123.         return -1;
  124.     }
  125.     }
  126.     hl->count--;
  127.     if (hl->count == 0)
  128.     {
  129.     ASSERT (hl->list == NULL);
  130.     hash_remove (h, hl->key);
  131.     if (h->hash_key == hash_string)
  132.         FREE (hl->key);
  133.     /* for debugging.. */
  134.     memset (hl, 0xff, sizeof (hashlist_t));
  135.     FREE (hl);
  136.     }
  137.     return 0;
  138. }
  139.  
  140. int
  141. hashlist_count (HASH * h, void *key)
  142. {
  143.     hashlist_t *hl;
  144.  
  145.     ASSERT (key != 0);
  146.     hl = hash_lookup (h, key);
  147. #if DEBUG
  148.     if (hl)
  149.     ASSERT (hashlist_validate (hl));
  150. #endif
  151.     return (hl ? hl->count : 0);
  152. }
  153.  
  154. LIST   *
  155. hashlist_lookup (HASH * h, void *key)
  156. {
  157.     hashlist_t *hl;
  158.  
  159.     ASSERT (key != 0);
  160.     hl = hash_lookup (h, key);
  161. #if DEBUG
  162.     if (hl)
  163.     ASSERT (hashlist_validate (hl));
  164. #endif
  165.     return hl ? hl->list : 0;
  166. }
  167.  
  168. void
  169. hashlist_free (hashlist_t * l)
  170. {
  171.     ASSERT (hashlist_validate (l));
  172.     /* TODO: currently this should only be called for hash tables which end
  173.      * up with leftover entries AND use strings as hash keys
  174.      */
  175.     FREE (l->key);
  176.     FREE (l);
  177. }
  178.  
  179. #if DEBUG
  180. int
  181. hashlist_validate (hashlist_t * l)
  182. {
  183.     ASSERT_RETURN_IF_FAIL (VALID_LEN (l, sizeof (hashlist_t)), 0);
  184.     ASSERT_RETURN_IF_FAIL (l->magic == MAGIC_HASHLIST, 0);
  185.     /* if there are members of the list, the count should be greater than
  186.      * zero.  nonzero count with null list is allowed.
  187.      */
  188.     ASSERT_RETURN_IF_FAIL ((l->list && l->count > 0) || l->list == 0, 0);
  189.     return 1;
  190. }
  191. #endif
  192.